package manipulador;

import java.io.IOException;
import java.util.ArrayList;

import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;

import agenda.Contato;



public class XmlcomSax extends DefaultHandler {


	private StringBuffer valorAtual = new StringBuffer(50); 
	private ArrayList<Contato> contatos = new ArrayList<Contato>();
	private Contato contatoTemp;
	private final String NO_CONTATO = "contato";
	private final String NO_NOME = "nome";
	private final String NO_ENDERECO = "endereco";
	private final String NO_TELEFONE = "telefone";
	private final String NO_EMAIL = "email";
	private final String ATT_ID = "id";
	
	public ArrayList<Contato> getContatos() {
		return contatos;
	}


	/**
	 * Constutor que inicializa os objetos necessários para fazer o parse
	 * do arquivo contato.xml
	 * @throws ParserConfigurationException
	 * @throws SAXException
	 * @throws IOException
	 */
	public void parse() throws ParserConfigurationException, SAXException, IOException {
		SAXParserFactory spf = SAXParserFactory.newInstance();
		SAXParser parser = spf.newSAXParser(); 
		parser.parse("agenda.xml", this);
	}

	/* 
	 * @see org.xml.sax.helpers.DefaultHandler#startDocument()
	 * Recebe notificação de início de um documento.
	 * O analisador SAX irá chamar esse método uma única vez, antes de qualquer outro evento
	 */
	public void startDocument() {
		System.out.println("Iniciando a leitura do XML");
	}
	
	/*
	 * @see org.xml.sax.helpers.DefaultHandler#endDocument()
	 * Recebe notificação do fim de um documento.
	 * O analisador SAX irá chamar esse método uma única vez, e será o último método chamado durante a análise. 
	 */
	public void endDocument() {
		System.out.println("Acabou a leitura do XML");
	}

	/**
	 * Indica que o parser achou o início de uma tag.
	 * Este evento fornece o nome do elemento, o nome e valor dos atributos
	 * deste elemento, e também pode fornecer as informações sobre o namespace.
	 */
	public void startElement(String uri, String localName, String tag, Attributes atributos){
		if (tag.equalsIgnoreCase(NO_CONTATO)){
			contatoTemp = new Contato();
		}

		//imprime o caminho da tag
		//System.out.print("\n" + tag + ": ");		
		//se o elemento possui atributos, imprime
		for (int i=0; i< atributos.getLength(); i++){
			//System.out.print(" " + atributos.getQName(i) + "=" + atributos.getValue(i));
			if (atributos.getQName(i).equalsIgnoreCase(ATT_ID)){
				contatoTemp.setId(Integer.parseInt(atributos.getValue(i)));
			}
		}
	}

	/** 
	 * Indica que o parser achou o fim de uma tag/elemento.
	 * Este evento fornece o nome do elemento, e também pode
	 * fornecer as informações sobre o namespace.
	 */
	public void endElement(String uri, String localName, String tag){

		//adiciona o contato na lista
		if (tag.equalsIgnoreCase(NO_CONTATO)){
			contatos.add(contatoTemp);
			//System.out.println();
		} 
		//senãoo, seta os atributos do contato
		else if (tag.equalsIgnoreCase(NO_NOME)){
			contatoTemp.setNome(valorAtual.toString().trim());
		} else if (tag.equalsIgnoreCase(NO_ENDERECO)){
			contatoTemp.setEndereco(valorAtual.toString().trim());
		} else if (tag.equalsIgnoreCase(NO_TELEFONE)){
			contatoTemp.setTelefone(valorAtual.toString().trim());
		} else if (tag.equalsIgnoreCase(NO_EMAIL)){
			contatoTemp.setEmail(valorAtual.toString().trim());
		}
		
		//limpa o valor Atual
		valorAtual.delete(0, valorAtual.length()); 
	}
	
	/**
	 * Indica que o parser achou algum Texto (Informaçõo).
	 */
	public void characters(char[] ch, int start, int length) {
		//System.out.print(String.copyValueOf(ch,start,length).trim());
		valorAtual.append(ch,start,length);
	}
	
	public void imprimeContatos(){
		for (int i=0; i<contatos.size(); i++){
			System.out.println(contatos.get(i));
		}
	}
	
	public static void main(String[] args){
		try {
			XmlcomSax reader = new XmlcomSax();
			reader.parse();
			reader.imprimeContatos();
			
		} catch (ParserConfigurationException e) {
			System.out.println("O parser nao foi configurado corretamente.");
			e.printStackTrace();
		} catch (SAXException e) {
			System.out.println("Problema ao fazer o parse do arquivo.");
			e.printStackTrace();
		} catch (IOException e) {
			System.out.println("O arquivo nao pode ser lido.");
			e.printStackTrace();
		}
	}
}
